`include "defines.vh"

module newmul(
    // 系统信号
    input wire rst,                    // 复位信号,高电平有效
    input wire clk,                    // 时钟信号,上升沿触发
    
    // 控制信号  
    input wire signed_mul_i,           // 乘法类型选择:1-有符号,0-无符号
    input wire start_i,                // 乘法启动信号:1-开始,0-停止
    
    // 操作数输入
    input wire[31:0] a_o,             // 被乘数(multiplicand)
    input wire[31:0] b_o,             // 乘数(multiplier)
    
    // 运算结果输出
    output reg[63:0] result_o,        // 64位乘法结果
    output reg ready_o                 // 运算完成标志:1-完成,0-未完成
);

    // 内部信号定义
    reg [31:0] temp_opa;              // 被乘数暂存器,存储转换后的被乘数
    reg [31:0] temp_opb;              // 乘数暂存器,存储转换后的乘数
    reg [63:0] pv;                    // 部分积寄存器,存储中间结果
    reg [63:0] ap;                    // 被乘数移位寄存器,用于逐位相乘
    reg [5:0] i;                      // 迭代计数器,控制32次移位加法
    reg [1:0] state;                  // 状态机状态寄存器

    // 主状态机实现:时序逻辑
    always @(posedge clk) begin
        if (rst) begin                 // 异步复位,初始化所有寄存器
            state <= `MulFree;         // 复位到空闲状态
            result_o <= {`ZeroWord, `ZeroWord};  // 清零结果寄存器
            ready_o <= `MulResultNotReady;       // 清零完成标志
            i <= 6'b0;                // 清零计数器
            pv <= 64'b0;              // 清零部分积
            ap <= 64'b0;              // 清零移位寄存器
            temp_opa <= 32'b0;        // 清零操作数暂存器
            temp_opb <= 32'b0;
        end else begin
            case (state)
                `MulFree: begin        // 空闲状态:等待乘法开始
                    if (start_i == `MulStart) begin     // 检测到开始信号
                        state <= `MulOn;                // 转入运算状态
                        i <= 6'b0;                      // 初始化计数器
                        
                        // 有符号乘法时进行符号处理:负数取补码
                        temp_opa <= (signed_mul_i && a_o[31]) ? (~a_o + 1) : a_o;
                        temp_opb <= (signed_mul_i && b_o[31]) ? (~b_o + 1) : b_o;
                        
                        // 初始化移位寄存器
                        ap <= {32'b0, (signed_mul_i && a_o[31]) ? (~a_o + 1) : a_o};
                        pv <= 64'b0;           // 清零部分积
                        ready_o <= `MulResultNotReady;  // 清零完成标志
                        result_o <= {`ZeroWord, `ZeroWord};
                    end
                end

                `MulOn: begin          // 计算状态:执行移位加法
                    if (i != 6'b100000) begin  // 32次迭代未完成
                        if (temp_opb[0]) begin  // 当前乘数位为1
                            pv <= pv + ap;      // 将被乘数加到部分积
                        end
                        ap <= {ap[62:0], 1'b0}; // 被乘数左移1位
                        temp_opb <= {1'b0, temp_opb[31:1]}; // 乘数右移1位
                        i <= i + 1;             // 计数器加1
                    end else begin              // 32次迭代完成
                        state <= `MulEnd;       // 转入结束状态
                        i <= 6'b0;              // 清零计数器
                        
                        // 有符号乘法且操作数符号不同时,结果取补码
                        if (signed_mul_i && (a_o[31] ^ b_o[31])) begin
                            pv <= ~pv + 1;
                        end
                    end
                end

                `MulEnd: begin         // 结束状态:输出结果
                    result_o <= pv;    // 输出最终结果
                    ready_o <= `MulResultReady; // 置位完成标志
                    
                    if (start_i == `MulStop) begin  // 检测到停止信号
                        state <= `MulFree;          // 返回空闲状态
                        ready_o <= `MulResultNotReady; 
                        result_o <= {`ZeroWord, `ZeroWord};
                    end
                end
            endcase
        end
    end

endmodule